/*
 * Copyright (c) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.api.client.generator.discovery.model;

import com.google.api.services.discovery.model.Jsonschema;
import com.google.common.base.Preconditions;


/**
 * @author Yaniv Inbar
 */
public abstract class SchemaBasedModel {
  private final Type type;
  private final String name;
  private final Jsonschema schema;
  private final ServiceModel service;

  public enum Type {
    REF,
    ANY,
    DATE_TIME,
    INT64,
    UINT64,
    STRING,
    FLOAT,
    DOUBLE,
    INT16,
    INT32,
    UINT32,
    BOOLEAN,
    OBJECT,
    ARRAY
  }

  SchemaBasedModel(ServiceModel service, String name, Jsonschema schema) {
    this.service = service;
    this.name = name;
    this.schema = schema;
    type = computeType(schema);
  }

  public final ServiceModel getParentService() {
    return service;
  }

  public final String getName() {
    return name;
  }

  final Jsonschema getSchema() {
    return schema;
  }

  public final String getDescription() {
    return schema.getDescription();
  }

  public final Type getType() {
    return type;
  }

  public ClassModel getRef() {
    Preconditions.checkState(getType() == Type.REF);
    return getParentService().getClassModels().get(getSchema().get$ref());
  }

  static Type computeType(Jsonschema schema) {
    if (schema.get$ref() != null) {
      return Type.REF;
    }
    if ("any".equals(schema.getType())) {
      return Type.ANY;
    }
    if ("boolean".equals(schema.getType())) {
      return Type.BOOLEAN;
    }
    if ("string".equals(schema.getType())) {
      if ("date-time".equals(schema.getFormat())) {
        return Type.DATE_TIME;
      }
      if ("int64".equals(schema.getFormat())) {
        return Type.INT64;
      }
      if ("uint64".equals(schema.getFormat())) {
        return Type.UINT64;
      }
      Preconditions.checkArgument(schema.getFormat() == null, schema.toString());
      return Type.STRING;
    }
    if ("number".equals(schema.getType())) {
      if ("float".equals(schema.getFormat())) {
        return Type.FLOAT;
      }
      Preconditions.checkArgument("double".equals(schema.getFormat()), schema.toString());
      return Type.DOUBLE;
    }
    if ("integer".equals(schema.getType())) {
      if ("int16".equals(schema.getFormat())) {
        return Type.INT16;
      }
      if ("int32".equals(schema.getFormat())) {
        return Type.INT32;
      }
      Preconditions.checkArgument("uint32".equals(schema.getFormat()), schema.toString());
      return Type.UINT32;
    }
    if ("array".equals(schema.getType())) {
      return Type.ARRAY;
    }
    Preconditions.checkArgument("object".equals(schema.getType()), schema.toString());
    return Type.OBJECT;
  }
}
